
#include <sys/resource.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <librally.h>

rp_pid_t rp_process_create(const char  *exe, char *const arg[], char *const env[])
{
	static char fname[] = "rp_process_create()";
	static char msg[] = "fatal error";
	Err err;
	rp_pid_t pid;
	struct stat exestat;
	FLOG_IN(fname);
	
#ifdef _LINUX
	/*	check the executable exists	*/ 
	if (stat(exe, &exestat) < 0) 
	{
		rp_log(LOG_DEBUG, fname, "Cannot find the executable: %s", exe);
		return E_ERROR;
	}
	
	pid = (rp_pid_t)fork();
    	switch (pid) 
	{
    		case (-1) : {
			rp_log(LOG_FATAL, fname, "Failed to create new process. Error: %s", strerror(errno));
			return -1;
		}
		case (0) : {
			break;
		}
		default : {
			FLOG_OUT(fname);
			return pid;
		}
    	}
	/* child */
      	alarm(0);	

	int i;
       for (i=0; i < sysconf(_SC_OPEN_MAX); i++)  close(i);
       for (i=1; i < NSIG; i++)  signal(i, SIG_DFL);

       execve(exe, arg, env);

	rp_log(LOG_FATAL, fname, "Failed to start %s", exe);
	exit(-1);
#elif _WIN32
#endif	// _WIN32
}

rp_pid_t rp_process_create_with_pipe(const char  *exe, char *const arg[], char *const env[], int fd[])
{
	char fname[] = "rp_process_create_with_pipe";
	char msg[] = "fatal error";
	Err err;
	rp_pid_t pid;
	struct stat exestat;
	FLOG_IN(fname);
	
#ifndef WIN32
	/*	check the executable exists	*/ 
	if (stat(exe, &exestat) < 0) 
	{
		rp_log(LOG_DEBUG, fname, "Cannot find the executable: %s", exe);
		return E_ERROR;
	}

	pid = (rp_pid_t)fork();
    	switch (pid) 
	{
    		case (-1) : {
			rp_log(LOG_FATAL, fname, "Failed to create new process. Error: %s", strerror(errno));
			return -1;
		}
		case (0) : {
			break;
		}
		default : {
			FLOG_OUT(fname);
			return pid;
		}
    	}
	/* child */
      	alarm(0);	

	close(fd[1]);					// child close the write end of the pipe	
      	dup2(fd[0], STDIN_FILENO);		// dup the read end of the pipe to Stdin
      	int i;
       for (i=2; i < sysconf(_SC_OPEN_MAX); i++)  close(i);		// do Not close Stdin, Stdout
       for (i=1; i < NSIG; i++)  signal(i, SIG_DFL);

       execve(exe, arg, env);
	 
	rp_log(LOG_FATAL, fname, "Failed to start %s", exe);
	exit(-1);
#else
#endif
}

Err rp_process_terminate(rp_pid_t pid, int signal)
{
	char fname[] = "rp_process_terminate()";
	char msg[] = "fatal error";
	Err err;
	FLOG_IN(fname);

	if (pid <= 0 || signal == 0)
	{
		rp_log(LOG_DEBUG, fname, "Invalid parameters: pid/signal");
		return E_INVALID;
	}

	if (kill(pid, signal) < 0)
	{
		rp_log(LOG_CRITICAL, fname, "Cannot send singal %d to process %d", signal, pid);
		return E_ERROR;
	}

	FLOG_OUT(fname);
	return E_OK;
}

